package mapper;

import config.JdbcConfig;
import lombok.Data;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author if
 * Description: What is it?
 * date: 2021/6/18 上午 08:54
 */
@Data
public class JdbcMapper<T> {
    private Class<T> clazz;
    private StringBuilder select ;
    private String surface;
    public JdbcMapper(Class<T> clazz,String surface) {
        this.clazz=clazz;
        this.surface=surface;
        this.select=new StringBuilder("select * from "+surface);
    }
    public int insertByPojo(T pojo){
        return 0;
    }
    public int insertAll(List<T> pojoList){
        return 0;
    }
    public int deleteById(String id){
        return 0;
    }
    public int deleteByIds(List<String> ids){
        return 0;
    }
    public int updateByPojo(T pojo){
        return 0;
    }
    public int updateAll(List<T> pojoList){
        return 0;
    }
    public T selectOneByOneFiled(QueryMapper<T> queryMapper){
        try{
            if(queryMapper.getMap().size()!=1){
                throw new SQLException("本方法仅支持单个参数\n参数过多请检查sql是否异常:"+queryMapper.getSql());
            }
            this.select.append(queryMapper.getSql());
            return toBean(queryMapper).get(0);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
    public T selectOne(QueryMapper<T> queryMapper){
        this.select.append(queryMapper.getSql());
        return toBean(queryMapper).get(0);
    }
    public List<T> selectList(QueryMapper<T> queryMapper){
        this.select.append(queryMapper.getSql());
        return toBean(queryMapper);
    }
    public List<T> selectAll(QueryMapper<T> queryMapper,int current,int count){
        select.append(" limit ").append(current).append(",").append(count);
        return toBean(queryMapper);
    }
    public void clear(){
        this.clazz=null;
        this.select.delete(0,this.select.length());
        this.select.append("select * from ").append(JdbcConfig.getDataBase());
    }

    /**
     * 结果集转换
     * @param queryMapper
     * @return
     */
    private List<T> toBean(QueryMapper<T> queryMapper){
        List<T> list=null;
        try{
            ResultSet resultSet = JdbcConfig.getStatement().executeQuery(this.select.toString());
            Field[] fields = queryMapper.getClazz().getDeclaredFields();
            while(resultSet.next()) {
                if(list==null){
                    list=new ArrayList<>();
                }
                T instance = queryMapper.getClazz().newInstance();
                for (Field field : fields) {
                    invokeSet(instance, field.getName(), resultSet.getString(field.getName()));
                }
                list.add(instance);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 反射bean的set方法
     * @param objectClass
     * @param fieldName
     * @return
     */
    public static Method getSetMethod(Class objectClass, String fieldName) {
        try {
            Class[] parameterTypes = new Class[1];
            Field field = objectClass.getDeclaredField(fieldName);
            parameterTypes[0] = field.getType();
            StringBuffer sb = new StringBuffer();
            sb.append("set");
            sb.append(fieldName.substring(0, 1).toUpperCase());
            sb.append(fieldName.substring(1));
            Method method = objectClass.getMethod(sb.toString(), parameterTypes);
            return method;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 反射执行set方法
     * @param o
     * @param fieldName
     * @param value
     */
    public static void invokeSet(Object o, String fieldName, Object value) {
        Method method = getSetMethod(o.getClass(), fieldName);
        try {
            method.invoke(o, new Object[] { value });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
